﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using EquipSecs300;
using SecsEquip;


namespace EquipViewAppNet
{
    public partial class PPFormatView : CMyFormEx
    {
        GEM_PPFormat PPFormat { get; set; }
        public PPFormatView()
        {
            InitializeComponent();

        }

        public override void UpdateData()
        {
            PPFormat = secsEquipHelper.PPFormat;
        }

        private void PPFormatView_FormClosing(object sender, FormClosingEventArgs e)
        {
            //m_pSecs.m_pOnPPFormatValueProc = null;
        }

        // 发送FromatPP
        private void buttonSend_Click(object sender, EventArgs e)
        {
            PPFormat.SendPP(textBoxPPID.Text);
        }

        // 请求FromatPP
        private void buttonRequst_Click(object sender, EventArgs e)
        {
            PPFormat.RequstPP(textBoxPPID.Text);
        }

        GEM_PPFormat_All pPFormat_All;
        private void btnPPFormatAdd_Click(object sender, EventArgs e)
        {
            if (pPFormat_All.IsPPFormatAdded)
            {
                MessageBox.Show("PPFormat Recipe Item List已经添加，无法重复添加");
                return;
            }
            if (pPFormat_All.recipeItem_DictOneSend == null || pPFormat_All.recipeItemType_DictOneSend == null)
            {
                MessageBox.Show("PPFormat Recipe Item List为空，无法添加到SDK");
                return;
            }
            pPFormat_All = PPFormat as GEM_PPFormat_All;
            if (pPFormat_All == null)
            {
                return;
            }
            bool isAllSucc = pPFormat_All.PPFormatAdd(pPFormat_All.recipeItem_DictOneSend, pPFormat_All.recipeItemType_DictOneSend);
            if (isAllSucc)
            {
                MessageBox.Show("SUCC: PPFormatAdd 全部添加成功！");
            }
            else
            {
                MessageBox.Show("ERR: PPFormatAdd 存在未添加成功项！");
            }
        }

        private void btnGetFormatPPList_Click(object sender, EventArgs e)
        {
            pPFormat_All = PPFormat as GEM_PPFormat_All;
            if (pPFormat_All == null)
            {
                return;
            }
            string ppid = textBoxPPID.Text;
            pPFormat_All.recipeItem_DictTwoSend = pPFormat_All.FuGetRecipeItemHandler?.Invoke(ppid, out pPFormat_All.recipeItemType_DictTwoSend);
            pPFormat_All.recipeItem_DictOneSend = pPFormat_All.ConvertRecipeItem_DictTwoToOne(pPFormat_All.recipeItem_DictTwoSend);
            pPFormat_All.recipeItemType_DictOneSend = pPFormat_All.ConvertRecipeItem_DictTwoToOne(pPFormat_All.recipeItemType_DictTwoSend);
            if (pPFormat_All.recipeItem_DictOneSend == null || pPFormat_All.recipeItemType_DictOneSend == null)
            {
                MessageBox.Show("PPFormat Recipe Item List添加失败，请检查PPID");
            }
            else
            {
                MessageBox.Show($"PPFormat Recipe Item List添加数量为: {pPFormat_All.recipeItem_DictOneSend.Count},PPFormat Recipe Type Item List添加数量为: {pPFormat_All.recipeItemType_DictOneSend.Count}");
            }
        }

        private void btnSaveFormatPP_Click(object sender, EventArgs e)
        {
            try
            {
                PPFormat.SaveFormatPPToCsv(textBoxPPID.Text, pPFormat_All.recipeItem_DictOneSend, pPFormat_All.recipeItemType_DictOneSend);
                MessageBox.Show("SUCC: 保存成功！");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"SUCC: 保存失败！-> {ex.Message}");
            }

        }

        #region 测试

        Dictionary<string, string> RecipeItem = new Dictionary<string, string>();
        private void btnTest_Click(object sender, EventArgs e)
        {
            var prm = new Prm();
            Dictionary<string, string> dictRecipeItemTem = new Dictionary<string, string>();
            Dictionary<string, string> dictRecipeItemTempType = new Dictionary<string, string>();
            GetRecipeItem(prm, "TrainModel", ref dictRecipeItemTem, ref dictRecipeItemTempType);
            RecipeItem = dictRecipeItemTem;
        }
        private static void GetRecipeItem(object obj, string strName, ref Dictionary<string, string> dictRecipeItemTemp, ref Dictionary<string, string> dictRecipeItemTempType)
        {
            if (obj == null)
            {
                return;
            }

            Type trainType = obj.GetType();
            PropertyInfo[] trainPropertyInfos = trainType.GetProperties();
            if (trainType.IsCustomClass())
            {
                foreach (PropertyInfo trainPropertyInfo in trainPropertyInfos)
                {
                    string name = string.IsNullOrEmpty(strName) ? trainPropertyInfo.Name : strName + "." + trainPropertyInfo.Name;

                    Type propertyType = trainPropertyInfo.PropertyType;
                    bool isCustomClass = propertyType.IsCustomClass();
                    bool isArray = propertyType.IsArrayType();
                    bool isList = propertyType.IsListNotArray();
                    bool isDic = propertyType.IsDictionaryType();
                    if (isCustomClass)
                    {
                        GetRecipeItem(trainPropertyInfo.GetValue(obj), name, ref dictRecipeItemTemp, ref dictRecipeItemTempType);
                    }
                    else if (trainPropertyInfo.Name == "Point")
                    {
                        GetRecipeItem(trainPropertyInfo.GetValue(obj), name, ref dictRecipeItemTemp, ref dictRecipeItemTempType);
                    }
                    else if (isArray)
                    {
                        Type elementType = propertyType.GetElementType();
                        var array = (Array)trainPropertyInfo.GetValue(obj, null);
                        int n = 0;
                        foreach (var item in array)
                        {
                            GetRecipeItem(item, name + $"[{n}]", ref dictRecipeItemTemp, ref dictRecipeItemTempType);
                            n++;
                        }
                    }
                    else if (isList)
                    {
                        Type[] genericArguments = propertyType.GetGenericArguments();
                        var list = (IList)trainPropertyInfo.GetValue(obj, null);
                        int n = 0;
                        foreach (var item in list)
                        {
                            GetRecipeItem(item, name + $"[{n}]", ref dictRecipeItemTemp, ref dictRecipeItemTempType);
                            n++;
                        }
                    }
                    else if (isDic)
                    {
                        Type keyType = propertyType.GetGenericArguments()[0];
                        Type valueType = propertyType.GetGenericArguments()[1];
                        var dec = (IDictionary)trainPropertyInfo.GetValue(obj, null);
                        foreach (DictionaryEntry item in dec)
                        {
                            GetRecipeItem(item.Value, name + $"[{item.Key}]", ref dictRecipeItemTemp, ref dictRecipeItemTempType);
                        }
                    }
                    else
                    {
                        Dictionary<string, string> item = new Dictionary<string, string>();
                        dictRecipeItemTemp.Add(name, trainPropertyInfo.GetValue(obj).ToString());
                        dictRecipeItemTempType.Add(name, trainPropertyInfo.PropertyType.Name);
                    }
                }
            }
            else if (!trainType.IsCustomClass() /*|| trainPropertyInfos.Length <= 0*/)
            {
                if (trainType.Name == "Point")
                {
                    PropertyInfo[] propertyInfos = trainType.GetProperties();
                    foreach (var item in propertyInfos)
                    {
                        var value = item.GetValue(obj, null);
                        GetRecipeItem(value, strName + $".{item.Name}", ref dictRecipeItemTemp, ref dictRecipeItemTempType);
                    }
                }
                else
                {
                    dictRecipeItemTemp.Add(strName, obj.ToString());
                    dictRecipeItemTempType.Add(strName, obj.GetType().Name);
                }
            }

        }

        private void btnTest2_Click(object sender, EventArgs e)
        {
            object prm = new Prm();

            Dictionary<string, string> dictRecipeItemTem = new Dictionary<string, string>();
            Dictionary<string, string> dictRecipeItemTempType = new Dictionary<string, string>();
            GetRecipeItem(prm, "TrainModel", ref dictRecipeItemTem, ref dictRecipeItemTempType);
            //prm.InspParam.ShiftMeasure.Progs[0].Dic_Methods[0].Dic_PointShapeFileTag[0] = "sttrr0011";
            dictRecipeItemTem["TrainModel.InspParam.ShiftMeasure.Progs[0].Dic_Methods[0].Dic_PointShapeFileTag[0]"] = "icwoncwocqi1221";
            dictRecipeItemTem["TrainModel.InspParam.ShiftMeasure.Enable"] = "False";
            dictRecipeItemTem["TrainModel.InspParam.GPSel_Insp.GP"] = "镜子F";
            dictRecipeItemTem["TrainModel.InspParam.ShiftMeasure.Point.X"] = "911";
            dictRecipeItemTem["TrainModel.InspParam.ShiftMeasure.Point.Y"] = "119";
            SetRecipeItem(prm, prm, "TrainModel", ref dictRecipeItemTem, ref dictRecipeItemTempType);
        }
        private void SetRecipeItem(object objPre, object obj, string strName, ref Dictionary<string, string> dictRecipeItemTemp, ref Dictionary<string, string> dictRecipeItemTypeTemp)
        {
            if (obj == null)
            {
                return;
            }

            Type trainType = obj.GetType();
            PropertyInfo[] trainPropertyInfos = trainType.GetProperties();

            foreach (PropertyInfo trainPropertyInfo in trainPropertyInfos)
            {
                string name = string.IsNullOrEmpty(strName) ? trainPropertyInfo.Name : strName + "." + trainPropertyInfo.Name;

                Type propertyType = trainPropertyInfo.PropertyType;
                bool isCustomClass = propertyType.IsCustomClass();
                bool isArray = propertyType.IsArrayType();
                bool isList = propertyType.IsListNotArray();
                bool isDic = propertyType.IsDictionaryType();

                if (isCustomClass)
                {
                    var inst = trainPropertyInfo.GetValue(obj);
                    SetRecipeItem(obj, inst, name, ref dictRecipeItemTemp, ref dictRecipeItemTypeTemp);
                }
                else if (propertyType.Name == "Point")
                {
                    var inst = trainPropertyInfo.GetValue(obj);
                    SetRecipeItem(obj, inst, name, ref dictRecipeItemTemp, ref dictRecipeItemTypeTemp);
                }
                else if (isArray)
                {
                    Type elementType = propertyType.GetElementType();
                    bool isCustomClassElement = elementType.IsCustomClass();

                    var array = (Array)trainPropertyInfo.GetValue(obj, null);
                    Type type = array.GetType();

                    int n = 0;
                    foreach (var item in array)
                    {
                        if (isCustomClassElement)
                        {
                            var inst = item;
                            SetRecipeItem(obj, inst, name + $"[{n}]", ref dictRecipeItemTemp, ref dictRecipeItemTypeTemp);
                            n++;
                        }
                        else
                        {
                            MethodInfo setValueMethod = type.GetMethod("SetValue", new Type[] { typeof(object), typeof(int) });
                            foreach (var recipeItem in dictRecipeItemTemp)
                            {
                                string nameTemp = name + $"[{n}]";
                                if (nameTemp == recipeItem.Key)
                                {
                                    if (!dictRecipeItemTypeTemp.ContainsKey(nameTemp))
                                    {
                                        continue;
                                    }
                                    string typeName = dictRecipeItemTypeTemp[nameTemp];
                                    int index1 = nameTemp.LastIndexOf("[");
                                    int index2 = nameTemp.LastIndexOf("]");
                                    var strIndex = nameTemp.Substring(index1 + 1, index2 - index1 - 1);
                                    int intIndex = UtilitiesConvert.StringToInt32(strIndex);
                                    #region 设置值
                                    try
                                    {
                                        switch (typeName)
                                        {
                                            case "String":
                                                {
                                                    string value = recipeItem.Value;
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            case "Boolean":
                                                {
                                                    bool value = UtilitiesConvert.StrStrToBoolean(recipeItem.Value);
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            case "Int32":
                                                {
                                                    int value = UtilitiesConvert.StringToInt32(recipeItem.Value);
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            case "Int16":
                                                {
                                                    Int16 value = UtilitiesConvert.StringToInt16(recipeItem.Value);
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            case "UInt16":
                                                {
                                                    UInt16 value = UtilitiesConvert.StringToUInt16(recipeItem.Value);
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            case "UInt32":
                                                {
                                                    UInt32 value = UtilitiesConvert.StringToUInt32(recipeItem.Value);
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            case "Double":
                                                {
                                                    double value = UtilitiesConvert.StringToDouble(recipeItem.Value);
                                                    setValueMethod.Invoke(array, new object[] { value, n });
                                                }
                                                break;
                                            default:
                                                {
                                                    PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{recipeItem.Value} 失败 -> 未找到对应设置方法");
                                                }
                                                break;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{recipeItem.Value} 失败 -> {ex.Message}");
                                    }
                                    #endregion
                                }
                            }
                            n++;
                        }
                    }
                }
                else if (isList)
                {
                    Type[] genericArguments = propertyType.GetGenericArguments();
                    bool isCustomClassElement = UtilitiesType.IsCustomClass(genericArguments[0]);

                    var list = (IList)trainPropertyInfo.GetValue(obj, null);
                    Type type = list.GetType();

                    int n = 0;
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (isCustomClassElement)
                        {
                            var inst = list[i];
                            SetRecipeItem(obj, inst, name + $"[{n}]", ref dictRecipeItemTemp, ref dictRecipeItemTypeTemp);
                            n++;
                        }
                        else
                        {
                            MethodInfo setValueMethod = type.GetMethod("set_Item");
                            foreach (var recipeItem in dictRecipeItemTemp)
                            {
                                string nameTemp = name + $"[{n}]";
                                if (nameTemp == recipeItem.Key)
                                {
                                    if (!dictRecipeItemTypeTemp.ContainsKey(nameTemp))
                                    {
                                        continue;
                                    }
                                    string typeName = dictRecipeItemTypeTemp[nameTemp];
                                    int index1 = nameTemp.LastIndexOf("[");
                                    int index2 = nameTemp.LastIndexOf("]");
                                    var strIndex = nameTemp.Substring(index1 + 1, index2 - index1 - 1);
                                    int intIndex = UtilitiesConvert.StringToInt32(strIndex);
                                    #region 设置值
                                    try
                                    {
                                        switch (typeName)
                                        {
                                            case "String":
                                                {
                                                    string value = recipeItem.Value;
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            case "Boolean":
                                                {
                                                    bool value = UtilitiesConvert.StrStrToBoolean(recipeItem.Value);
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            case "Int32":
                                                {
                                                    int value = UtilitiesConvert.StringToInt32(recipeItem.Value);
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            case "Int16":
                                                {
                                                    Int16 value = UtilitiesConvert.StringToInt16(recipeItem.Value);
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            case "UInt16":
                                                {
                                                    UInt16 value = UtilitiesConvert.StringToUInt16(recipeItem.Value);
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            case "UInt32":
                                                {
                                                    UInt32 value = UtilitiesConvert.StringToUInt32(recipeItem.Value);
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            case "Double":
                                                {
                                                    double value = UtilitiesConvert.StringToDouble(recipeItem.Value);
                                                    setValueMethod.Invoke(list, new object[] { n, value });
                                                }
                                                break;
                                            default:
                                                {
                                                    PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{recipeItem.Value} 失败 -> 未找到对应设置方法");
                                                }
                                                break;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{recipeItem.Value} 失败 -> {ex.Message}");
                                    }
                                    #endregion
                                }
                            }
                            n++;
                        }
                    }
                }
                else if (isDic)
                {
                    Type keyType = propertyType.GetGenericArguments()[0];
                    Type valueType = propertyType.GetGenericArguments()[1];
                    var dec = (IDictionary)trainPropertyInfo.GetValue(obj, null);
                    IDictionary decTemp = UtilitiesSundry.CopyDictionary(dec);
                    Type dictType = dec.GetType();
                    foreach (DictionaryEntry item in decTemp)
                    {
                        if (valueType.IsCustomClass())
                        {
                            var inst = item.Value;
                            SetRecipeItem(obj, inst, name + $"[{item.Key}]", ref dictRecipeItemTemp, ref dictRecipeItemTypeTemp);
                        }
                        else
                        {
                            PropertyInfo itemProperty = dictType.GetProperty("Item");

                            foreach (var recipeItem in dictRecipeItemTemp)
                            {
                                string nameTemp = name + $"[{item.Key}]";
                                if (nameTemp == recipeItem.Key)
                                {
                                    if (!dictRecipeItemTypeTemp.ContainsKey(nameTemp))
                                    {
                                        continue;
                                    }
                                    string typeName = dictRecipeItemTypeTemp[nameTemp];
                                    #region 设置值
                                    try
                                    {
                                        switch (typeName)
                                        {
                                            case "String":
                                                {
                                                    string value = recipeItem.Value;
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            case "Boolean":
                                                {
                                                    bool value = UtilitiesConvert.StrStrToBoolean(recipeItem.Value);
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            case "Int32":
                                                {
                                                    int value = UtilitiesConvert.StringToInt32(recipeItem.Value);
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            case "Int16":
                                                {
                                                    Int16 value = UtilitiesConvert.StringToInt16(recipeItem.Value);
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            case "UInt16":
                                                {
                                                    UInt16 value = UtilitiesConvert.StringToUInt16(recipeItem.Value);
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            case "UInt32":
                                                {
                                                    UInt32 value = UtilitiesConvert.StringToUInt32(recipeItem.Value);
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            case "Double":
                                                {
                                                    double value = UtilitiesConvert.StringToDouble(recipeItem.Value);
                                                    itemProperty.SetValue(dec, value, new object[] { item.Key });
                                                }
                                                break;
                                            default:
                                                {
                                                    PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{item.Value} 失败 -> 未找到对应设置方法");
                                                }
                                                break;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{item.Value} 失败 -> {ex.Message}");
                                    }
                                    #endregion
                                }
                            }
                        }
                    }
                }
                else
                {
                    foreach (var item in dictRecipeItemTemp)
                    {
                        if (name == item.Key)
                        {
                            SetRecipeItemValue(ref dictRecipeItemTypeTemp, trainPropertyInfo, item, ref obj, name);
                        }
                    }
                    /*值类型Point，设置新值后需要拿到值，在上层类重新赋值*/
                    if (trainType.Name == "Point")
                    {
                        var type = objPre.GetType();
                        var propInfos = type.GetProperties();
                        foreach (var item in propInfos)
                        {
                            var subType = item.PropertyType;
                            if (subType.Name == "Point")
                            {
                                item.SetValue(objPre, obj);
                            }
                        }
                    }
                    /****************************************************/
                }
            }
        }

        private void SetRecipeItemValue(ref Dictionary<string, string> dictRecipeItemTypeTemp, PropertyInfo trainPropertyInfo, KeyValuePair<string, string> item, ref object obj, string name)
        {
            string typeName = dictRecipeItemTypeTemp[name];
            try
            {
                switch (typeName)
                {
                    case "String":
                        {
                            string n = item.Value;
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    case "Boolean":
                        {
                            bool n = UtilitiesConvert.StrStrToBoolean(item.Value);
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    case "Int32":
                        {
                            int n = UtilitiesConvert.StringToInt32(item.Value);
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    case "Double":
                        {
                            double n = UtilitiesConvert.StringToDouble(item.Value);
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    case "Int16":
                        {
                            Int16 n = UtilitiesConvert.StringToInt16(item.Value);
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    case "UInt16":
                        {
                            UInt16 n = UtilitiesConvert.StringToUInt16(item.Value);
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    case "UInt32":
                        {
                            UInt32 n = UtilitiesConvert.StringToUInt32(item.Value);
                            trainPropertyInfo.SetValue(obj, n);
                        }
                        break;
                    default:
                        {
                            PPFormat.LogMsg($"ERR: 变量: {trainPropertyInfo.Name}, 类型:{typeName}, 设置值{item.Value} 失败 -> 未找到对应设置方法");
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                PPFormat.LogMsg($"ERR: 变量{typeName} 类型 {trainPropertyInfo.Name} 设置值{item.Value} 失败 -> {ex.Message}");
            }

        }

        #endregion


    }
}
